package com.fjeld.middleware.util.serverstatus;

import static com.fjeld.middleware.util.serverstatus.ServerStatus.*;

import com.fjeld.middleware.constants.PropertiesManager;
import com.fjeld.middleware.jaxb.V1Heartbeat;
import org.apache.log4j.Logger;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.UUID;

/**
 * Created by IntelliJ IDEA.
 * User: fjeld
 * Date: 11/12/2011
 * Time: 20:45
 * <p/>
 * A capsule that monitors heartbeats from one server. If status changes, sends out a notification.
 */
public class ServerStatusCapsule extends Observable implements ActionListener
{
    private static final Logger logger = Logger.getLogger(ServerStatusCapsule.class);
    private static long heartbeatUnresponsiveInterval = 5000;

    static
    {
        String interval = PropertiesManager.getProperties().getProperty("Heartbeat.UnresponsiveInterval");
        if (null != interval)
        {
            heartbeatUnresponsiveInterval = Long.parseLong(interval);
        }

    }

    private String serverName, serverHostName, serverUUID;
    private ServerStatus serverStatus;
    private long lastUpdateTimeInMillis, unresponsiveSinceTimeInMills = 0;

    public ServerStatusCapsule(V1Heartbeat v1Heartbeat)
    {
        serverName = v1Heartbeat.getServername();
        serverHostName = v1Heartbeat.getHostname();
        serverStatus = ServerStatus.valueOf(v1Heartbeat.getStatus());
        serverUUID = UUID.randomUUID().toString();
        lastUpdateTimeInMillis = System.currentTimeMillis();
        logger.info("Heartbeat unresponsive interval: " + heartbeatUnresponsiveInterval);
        logger.debug("Created for " + serverName + " on " + serverHostName + " w/status " + serverStatus);
    }

    public void update(V1Heartbeat v1Heartbeat)
    {
        lastUpdateTimeInMillis = System.currentTimeMillis();
        ServerStatus newStatus = ServerStatus.valueOf(v1Heartbeat.getStatus());
        if (!serverStatus.equals(newStatus))
        {
            serverStatus = newStatus;
            setChanged();
            notifyObservers(serverStatus);
        }
    }

    public String getServerName()
    {
        return serverName;
    }

    public String getServerHostName()
    {
        return serverHostName;
    }

    public ServerStatus getServerStatus()
    {
        return serverStatus;
    }

    public void actionPerformed(ActionEvent actionEvent)
    {
        //logger.info("Checking status for " + serverName);
        if (serverStatus.equals(Unresponsive) || serverStatus.equals(Unknown)
                || serverStatus.equals(Down))
        {
            // Nothing to do
            return;
        }

        // However, if in any other state and the server stops heartbeating then
        // it needs to be flagged.
        long nowTimeInMillis = System.currentTimeMillis();
        long timeSinceLastHB = nowTimeInMillis - lastUpdateTimeInMillis;
        if (timeSinceLastHB > heartbeatUnresponsiveInterval)
        {
            unresponsiveSinceTimeInMills = nowTimeInMillis;
            serverStatus = Unresponsive;
            logger.fatal("Unresponsive server found: " + serverName + " on host " + serverHostName);
            setChanged();
            notifyObservers(serverStatus);
        }

        //logger.info("Status for " + serverName + " is " + serverStatus.toString());
    }

}
